package edu.scsu.csci.interceptor;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import edu.scsu.csci.IInterceptor;
import edu.scsu.csci.core.ApplicationConfiguration;

/**
 * A composite of interceptors. 
 *
 * @author Maqbool Khan
 * @since jdk 1.5
 * @see
 */
public class InterceptorChain  implements IInterceptorChain<Object>{
	
	/**
	 * Interceptors defined for the operation.
	 */
	protected List<IInterceptor> interceptors = new ArrayList<IInterceptor>();
	
	/**
	 * The return code returned by the cuurent interceptor.
	 */
	protected EInterceptorFlow interceptorFlow = EInterceptorFlow.CONTINUE;
	
	
	/**
	 * creates an instance of InterceptorChain.
	 */
	public InterceptorChain() {
		
	}
	
	/**
	 * @return
	 */
	public List<IInterceptor> getInterceptors() {
		return interceptors;
	}
	
	/* (non-Javadoc)
	 * @see edu.scsu.csci.interceptor.IInterceptor#preProcess(edu.scsu.csci.context.ActionContext)
	 */
	public EInterceptorFlow preProcess(Object object, ServletRequest request, ServletResponse response) {
		
		boolean exit = false;
		for (int i = 0, length = interceptors.size(); i < length && !exit; i++) {
			try {
				this.interceptorFlow = interceptors.get(i).preProcess(object, request, response);
				switch(this.interceptorFlow)	{
					case CONTINUE: continue;
					case SKIP_NEXT: 
						i++;
						ApplicationConfiguration.getInstance(null).getLogger().info("AInterceptor:", interceptors.get(i + 1).getClass().getName(), "pre-processing has been skipped.");
						break;
					case SKIP_PRE_PROCESSING:
						exit = true;
						ApplicationConfiguration.getInstance(null).getLogger().info("Interceptors pre-processing has been skipped.");
						break;
					case SKIP_POST_PROCESSING:
						ApplicationConfiguration.getInstance(null).getLogger().info("Interceptors post-processing has been skipped.");
						continue;
					case DISCARD_REQUEST:
						exit = true;
						ApplicationConfiguration.getInstance(null).getLogger().info("The request has been discarded.");
						break;
				}
				
			}catch (Exception e) {
				break;
			}
		}
		return this.interceptorFlow;
	}
	
	/* (non-Javadoc)
	 * @see edu.scsu.csci.interceptor.IInterceptor#postProcess(edu.scsu.csci.context.ActionContext)
	 */
	public EInterceptorFlow postProcess(Object object, ServletRequest request, ServletResponse response) {
		if( 	this.interceptorFlow == EInterceptorFlow.SKIP_POST_PROCESSING
					|| this.interceptorFlow == EInterceptorFlow.DISCARD_REQUEST)	{
			//TODO: Add logging statement MK
			return this.interceptorFlow;
		}
		
		boolean exit = false;
		for (int i = 0, length = interceptors.size(); i < length && !exit; i++) {
			try {
				this.interceptorFlow = interceptors.get(i).postProcess(object, request, response);
				switch(this.interceptorFlow){
					case SKIP_NEXT: 
						i++;
						break;
					case DISCARD_REQUEST:
						exit = true;
						//TODO: Add logging statement MK
						break;
					case SKIP_POST_PROCESSING:
						exit = true;
						//TODO: Add logging statement MK
						break;
					default: continue;
				}
				
			}catch (Exception e) {
				break;
			}
		}
		return this.interceptorFlow;
	}
	
	/**
	 * @param interceptor
	 */
	public void addInterceptor(IInterceptor interceptor) {
		
		if (interceptor == null) {
			throw new IllegalArgumentException();
		}
		//TODO: Add logging statement MK
		this.interceptors.add(interceptor);
		
	}
	
	/**
	 * @param interceptor
	 */
	public void addInterceptors(List<IInterceptor> interceptors) {
		
		if (interceptors == null) {
			throw new IllegalArgumentException();
		}
		//TODO: Add logging statement MK
		this.interceptors.addAll(interceptors);
		
	}
	
}
